#!/usr/bin/env python

from PIL import Image
from random import randint
from math import floor, sqrt, pow
from time import gmtime, strftime
import time
import pickle

from jplur.Hash import Hash 
import jplur




class game_map():
	def __init__(self):
		self.dimension = [256, 256]
		self.sector_size = 8
		self.z_levels = 9
		self.map = []
		self.entity_hash = Hash(self.sector_size)
		self.object_hash = Hash(self.sector_size)
		
		try:
			self.load()
		except:
		
			images = []
			for i in range(self.z_levels):
				images.append( Image.open("./map/"+str(i)+".png") )
			self.construct(images, self.dimension[0], self.dimension[1])
			self.save()
		

		
	def construct(self, images, w, h):
		
		NOTHING = (0, 0, 0)
		
		SAND = (243, 208, 112)
		DIRT = (129, 98, 12)
		ROCK1 = (158, 158, 158)
		ROCK2 = (207, 207, 207)
		COPPER = (207, 102, 0)
		IRON = (87, 87, 87)
		RUBIES = (227, 37, 176)
		
		GRASS = (6, 91, 0)
		BRUSH = (82, 126, 26)
		STONE_FLOOR = (42, 42, 42)
		
		DOWN_STAIR = (255, 0, 187)
		UP_STAIR = (0,255,30)
		
		
		#map[ z, x, y] ?
		
		for k in range(len(images)):
			level = images[k]
			pix = level.load()
			self.map.append([])
			for i in range(h):
				
				self.map[k].append([])
				
				for j in range(w):
					if pix[j,i] == NOTHING:
						t = 0
					if pix[j,i] == SAND:
						t = 1
					if pix[j,i] == DIRT:
						t = 2
					if pix[j,i] == ROCK1:
						t = 3
					if pix[j,i] == ROCK2:
						t = 4
					if pix[j,i] == COPPER:
						t = 5
					if pix[j,i] == IRON:
						t = 6
					if pix[j,i] == RUBIES:
						t = 7
						
					if pix[j,i] == GRASS:
						t = -1
					if pix[j,i] == BRUSH:
						t = -2
					if pix[j,i] == STONE_FLOOR:
						t = -3
					if pix[j,i] == DOWN_STAIR:
						t = -4
					if pix[j,i] == UP_STAIR:
						t = -5
					self.map[k][i].append( t )
					
	def save(self):
		print "Saving map.."
		savefile = open('./map/'+'default'+'.map', 'w')
		pickle.dump(self.map, savefile)
		savefile.close()
		print "Map saved!"
		
	def load(self):
		print "Loading map.."
		savefile = open('./map/'+'default'+'.map', 'r')
		self.map = pickle.load(savefile)
		savefile.close()
		print "Map loaded!"
		
	def get_sector(self, sector): 
	
		z =  sector[0]
		x = sector[1]
		y = sector[2]
		x_slice = self.map[z][ x*self.sector_size : x*self.sector_size+self.sector_size ]
		y_slice = []
		for entry in x_slice:
			y_slice.append( entry[y*self.sector_size : y*self.sector_size+self.sector_size ] )
			
		return y_slice
		
		
	def key(self, point):
		cell_size = self.sector_size
		return (
			int(point[0]), #z 
			int((floor(point[1]/cell_size))),
			int((floor(point[2]/cell_size)))
		)
		
	def total_player_view(self, loc):
		map = []
		key = self.key(loc)
		for x in range(3):
			for y in range(3):
				#sending the sector key along with the map data, can just slice it into client map
				map.append( [[key[0],key[1]+(x-1),key[2]+(y-1)], self.get_sector( [key[0], key[1]+(x-1), key[2]+(y-1)] )] )
		return map
		
	def cell_change_view(self, loc, direction): #direction is something like [0,1,-1]
		#returns all the cells necessary by the move direction
		#can be used for leaving notifications with a negative direction
		map = []
		key = self.key(loc)
		print direction
		table	 = { 	(0,-1,-1): [ [0,-1,1], [0,-1,0], [0,-1,-1], [0,0,-1], [0,1,-1] ],
						(0,-1,0): [ [0,-1,-1], [0,-1,0], [0,-1,1] ],
						(0,-1,1): [ [0,-1,-1], [0,-1,0], [0,-1,1],[0,0,1],[0,1,1] ],
						(0,0,-1): [ [0,-1,-1], [0,0,-1], [0,1,-1] ],
						(0,0,1): [ [0,-1,1], [0,0,1], [0,1,1] ],
						(0,1,-1): [ [0,-1,-1], [0,0,-1], [0,1,-1], [0,1,0], [0,1,1] ],
						(0,1,0): [ [0,1,-1], [0,1,0], [0,1,1] ],
						(0,1,1): [ [0,-1,1], [0,0,1], [0,1,1], [0,1,0], [0,1,-1] ],
						(1,0,0): [ [1,-1,-1], [1,0,-1], [1,1,-1], [1,-1,0], [1,0,0], [1,1,0], [1,-1,1], [1,0,1], [1,1,1] ],
						(-1,0,0): [ [-1,-1,-1], [-1,0,-1], [-1,1,-1], [-1,-1,0], [-1,0,0], [-1,1,0], [-1,-1,1], [-1,0,1], [-1,1,1] ],
						(0,0,0): [ [0,-1,-1], [0,0,-1], [0,1,-1], [0,-1,0], [0,0,0], [0,1,0], [0,-1,1], [0,0,1], [0,1,1] ]
		}
		
		if tuple(direction) in table:
			
			for thing in table[tuple(direction)]:
				map.append( [[key[0]+thing[0],key[1]+thing[1],key[2]+thing[2]], self.get_sector( [key[0]+thing[0],key[1]+thing[1],key[2]+thing[2]] )] )
		return map
		
	def cell_change_view_keys(self, loc, direction):
		map = []
		key = self.key(loc)

		table	 = { 	(0,-1,-1): [ [0,-1,1], [0,-1,0], [0,-1,-1], [0,0,-1], [0,1,-1] ],
						(0,-1,0): [ [0,-1,-1], [0,-1,0], [0,-1,1] ],
						(0,-1,1): [ [0,-1,-1], [0,-1,0], [0,-1,1],[0,0,1],[0,1,1] ],
						(0,0,-1): [ [0,-1,-1], [0,0,-1], [0,1,-1] ],
						(0,0,1): [ [0,-1,1], [0,0,1], [0,1,1] ],
						(0,1,-1): [ [0,-1,-1], [0,0,-1], [0,1,-1], [0,1,0], [0,1,1] ],
						(0,1,0): [ [0,1,-1], [0,1,0], [0,1,1] ],
						(0,1,1): [ [0,-1,1], [0,0,1], [0,1,1], [0,1,0], [0,1,-1] ],
						(1,0,0): [ [1,-1,-1], [1,0,-1], [1,1,-1], [1,-1,0], [1,0,0], [1,1,0], [1,-1,1], [1,0,1], [1,1,1] ],
						(-1,0,0): [ [-1,-1,-1], [-1,0,-1], [-1,1,-1], [-1,-1,0], [-1,0,0], [-1,1,0], [-1,-1,1], [-1,0,1], [-1,1,1] ],
						(0,0,0): [ [0,-1,-1], [0,0,-1], [0,1,-1], [0,-1,0], [0,0,0], [0,1,0], [0,-1,1], [0,0,1], [0,1,1] ]
		}
		if tuple(direction) in table:
		
			for thing in table[tuple(direction)]:
				map.append( [key[0]+thing[0],key[1]+thing[1],key[2]+thing[2]] )
		
		return map
		
		
	def sync_maps(self):
		return [self.dimension, self.sector_size, self.z_levels]
	
	def tile_at(self, location):
		return self.map[location[0]][location[1]][location[2]]
	
	def things_in_tile(self, location):
		entities = []
		for entity in self.entity_hash.query(location):
			if entity.location == location:
				entities.append(entity)
		return entities
		
	def things_in_view(self, location):
		candidates = []
		for entry in jplur.map.cell_change_view_keys(location, [0,0,0]):
				found = jplur.map.entity_hash.query_key(entry)
				for entry in found:
					
					if entry != self:
						candidates.append(entry)
		return candidates
		
		
